#include "stdafx.h"
#include "FrustumClass.h"


CFrustumClass::CFrustumClass(void)
{
}


CFrustumClass::~CFrustumClass(void)
{
}

void CFrustumClass::ConstructFrustum(float fScreenDepth, D3DXMATRIX d3dProj, D3DXMATRIX d3dView)
{
	float fZMin;
	float fRadius;
	D3DXMATRIX d3dMatrix;


	// Calculate the minimum Z distance in the frustum.
	fZMin = -d3dProj._43 / d3dProj._33;
	fRadius = fScreenDepth / (fScreenDepth - fZMin);
	d3dProj._33 = fRadius;
	d3dProj._43 = -fRadius * fZMin;

	// Create the frustum matrix from the view matrix and updated projection matrix.
	D3DXMatrixMultiply(&d3dMatrix, &d3dView, &d3dProj);

	// Near
	m_d3dPlanes[0].a = d3dMatrix._14 + d3dMatrix._13;
	m_d3dPlanes[0].b = d3dMatrix._24 + d3dMatrix._23;
	m_d3dPlanes[0].c = d3dMatrix._34 + d3dMatrix._33;
	m_d3dPlanes[0].d = d3dMatrix._44 + d3dMatrix._43;
	D3DXPlaneNormalize(&m_d3dPlanes[0], &m_d3dPlanes[0]);

	// Far
	m_d3dPlanes[1].a = d3dMatrix._14 - d3dMatrix._13; 
	m_d3dPlanes[1].b = d3dMatrix._24 - d3dMatrix._23;
	m_d3dPlanes[1].c = d3dMatrix._34 - d3dMatrix._33;
	m_d3dPlanes[1].d = d3dMatrix._44 - d3dMatrix._43;
	D3DXPlaneNormalize(&m_d3dPlanes[1], &m_d3dPlanes[1]);

	// Left
	m_d3dPlanes[2].a = d3dMatrix._14 + d3dMatrix._11; 
	m_d3dPlanes[2].b = d3dMatrix._24 + d3dMatrix._21;
	m_d3dPlanes[2].c = d3dMatrix._34 + d3dMatrix._31;
	m_d3dPlanes[2].d = d3dMatrix._44 + d3dMatrix._41;
	D3DXPlaneNormalize(&m_d3dPlanes[2], &m_d3dPlanes[2]);

	// Right
	m_d3dPlanes[3].a = d3dMatrix._14 - d3dMatrix._11; 
	m_d3dPlanes[3].b = d3dMatrix._24 - d3dMatrix._21;
	m_d3dPlanes[3].c = d3dMatrix._34 - d3dMatrix._31;
	m_d3dPlanes[3].d = d3dMatrix._44 - d3dMatrix._41;
	D3DXPlaneNormalize(&m_d3dPlanes[3], &m_d3dPlanes[3]);

	// Top
	m_d3dPlanes[4].a = d3dMatrix._14 - d3dMatrix._12; 
	m_d3dPlanes[4].b = d3dMatrix._24 - d3dMatrix._22;
	m_d3dPlanes[4].c = d3dMatrix._34 - d3dMatrix._32;
	m_d3dPlanes[4].d = d3dMatrix._44 - d3dMatrix._42;
	D3DXPlaneNormalize(&m_d3dPlanes[4], &m_d3dPlanes[4]);

	//Bottom
	m_d3dPlanes[5].a = d3dMatrix._14 + d3dMatrix._12;
	m_d3dPlanes[5].b = d3dMatrix._24 + d3dMatrix._22;
	m_d3dPlanes[5].c = d3dMatrix._34 + d3dMatrix._32;
	m_d3dPlanes[5].d = d3dMatrix._44 + d3dMatrix._42;
	D3DXPlaneNormalize(&m_d3dPlanes[5], &m_d3dPlanes[5]);
}

bool CFrustumClass::CheckPoint(float fXPos, float fYPos, float fZPos)
{
	for(int i = 0; i < 6; ++i) 
	{
		if(D3DXPlaneDotCoord(&m_d3dPlanes[i], &D3DXVECTOR3(fXPos, fYPos, fZPos)) < 0.0f)
		{
			return false;
		}
	}

	return true;
}

bool CFrustumClass::CheckCube(float fXCenter, float fYCenter, float fZCenter, float fRadius)
{
	for(int i = 0; i < 6; ++i) 
	{
		if(D3DXPlaneDotCoord(&m_d3dPlanes[i], &D3DXVECTOR3((fXCenter - fRadius), (fYCenter - fRadius), (fZCenter - fRadius))) >= 0.0f)
		{
			continue;
		}

		if(D3DXPlaneDotCoord(&m_d3dPlanes[i], &D3DXVECTOR3((fXCenter + fRadius), (fYCenter - fRadius), (fZCenter - fRadius))) >= 0.0f)
		{
			continue;
		}

		if(D3DXPlaneDotCoord(&m_d3dPlanes[i], &D3DXVECTOR3((fXCenter - fRadius), (fYCenter + fRadius), (fZCenter - fRadius))) >= 0.0f)
		{
			continue;
		}

		if(D3DXPlaneDotCoord(&m_d3dPlanes[i], &D3DXVECTOR3((fXCenter + fRadius), (fYCenter + fRadius), (fZCenter - fRadius))) >= 0.0f)
		{
			continue;
		}

		if(D3DXPlaneDotCoord(&m_d3dPlanes[i], &D3DXVECTOR3((fXCenter - fRadius), (fYCenter - fRadius), (fZCenter + fRadius))) >= 0.0f)
		{
			continue;
		}

		if(D3DXPlaneDotCoord(&m_d3dPlanes[i], &D3DXVECTOR3((fXCenter + fRadius), (fYCenter - fRadius), (fZCenter + fRadius))) >= 0.0f)
		{
			continue;
		}

		if(D3DXPlaneDotCoord(&m_d3dPlanes[i], &D3DXVECTOR3((fXCenter - fRadius), (fYCenter + fRadius), (fZCenter + fRadius))) >= 0.0f)
		{
			continue;
		}

		if(D3DXPlaneDotCoord(&m_d3dPlanes[i], &D3DXVECTOR3((fXCenter + fRadius), (fYCenter + fRadius), (fZCenter + fRadius))) >= 0.0f)
		{
			continue;
		}

		return false;
	}

	return true;
}

bool CFrustumClass::CheckSphere(float fXCenter, float fYCenter, float fZCenter, float fRadius)
{
	for(int i = 0; i < 6; ++i) 
	{
		if(D3DXPlaneDotCoord(&m_d3dPlanes[i], &D3DXVECTOR3(fXCenter, fYCenter, fZCenter)) < -fRadius)
		{
			return false;
		}
	}

	return true;
}

bool CFrustumClass::CheckRectangle(float fXCenter, float fYCenter, float fZCenter, float fXSize, float fYSize, float fZSize)
{
	for(int i = 0; i < 6; ++i)
	{
		if(D3DXPlaneDotCoord(&m_d3dPlanes[i], &D3DXVECTOR3((fXCenter - fXSize), (fYCenter - fYSize), (fZCenter - fZSize))) >= 0.0f)
		{
			continue;
		}

		if(D3DXPlaneDotCoord(&m_d3dPlanes[i], &D3DXVECTOR3((fXCenter + fXSize), (fYCenter - fYSize), (fZCenter - fZSize))) >= 0.0f)
		{
			continue;
		}

		if(D3DXPlaneDotCoord(&m_d3dPlanes[i], &D3DXVECTOR3((fXCenter - fXSize), (fYCenter + fYSize), (fZCenter - fZSize))) >= 0.0f)
		{
			continue;
		}

		if(D3DXPlaneDotCoord(&m_d3dPlanes[i], &D3DXVECTOR3((fXCenter - fXSize), (fYCenter - fYSize), (fZCenter + fZSize))) >= 0.0f)
		{
			continue;
		}

		if(D3DXPlaneDotCoord(&m_d3dPlanes[i], &D3DXVECTOR3((fXCenter + fXSize), (fYCenter + fYSize), (fZCenter - fZSize))) >= 0.0f)
		{
			continue;
		}

		if(D3DXPlaneDotCoord(&m_d3dPlanes[i], &D3DXVECTOR3((fXCenter + fXSize), (fYCenter - fYSize), (fZCenter + fZSize))) >= 0.0f)
		{
			continue;
		}

		if(D3DXPlaneDotCoord(&m_d3dPlanes[i], &D3DXVECTOR3((fXCenter - fXSize), (fYCenter + fYSize), (fZCenter + fZSize))) >= 0.0f)
		{
			continue;
		}

		if(D3DXPlaneDotCoord(&m_d3dPlanes[i], &D3DXVECTOR3((fXCenter + fXSize), (fYCenter + fYSize), (fZCenter + fZSize))) >= 0.0f)
		{
			continue;
		}

		return false;
	}

	return true;
}